using System;
using System.Collections.Generic;
using System.Text;
using DBAccess;
using FitnessClub.Bll.ServiceManager;


namespace FitnessClub.Bll.StaffManager
{
    public class StaffManager : Facade.Interface.IStaff
    {
        private NHibernateDao<DBAccess.employees, int> tabelaEmployee = new NHibernateDao<employees, int>();
        private NHibernateDao<DBAccess.dict_employees, int> tabelaDictEmployee = new NHibernateDao<dict_employees, int>();
        private NHibernateDao<DBAccess.personal_data, int> tabelaPersonalData = new NHibernateDao<personal_data, int>();
        private NHibernateDao<DBAccess.services_employees, int> tabelaServicesEmployees = new NHibernateDao<services_employees, int>();
        private NHibernateDao<DBAccess.services, int> tabelaServices = new NHibernateDao<services, int>();
        private NHibernateDao<DBAccess.employees_break, int> tabelaEmployeesHolidays = new NHibernateDao<employees_break, int>();
        private NHibernateDao<DBAccess.dict_break, int> tabelaEmployeesHolidayTypes = new NHibernateDao<dict_break, int>();

        public bool bindEmployeeToService(ReqBEmp req)
        {
            NHibernate.Expression.ICriterion[] searchCrit = new NHibernate.Expression.ICriterion[2];
            searchCrit[0] = NHibernate.Expression.Expression.Eq("id_employees", req.EmployeeID);
            searchCrit[1] = NHibernate.Expression.Expression.Eq("id_services", req.ServiceID);
            List<services_employees> elements = tabelaServicesEmployees.GetByCriteria(searchCrit);
            if (elements.Count > 0)
                return false;
            DBAccess.services_employees semp = new DBAccess.services_employees();
            try
            {
                semp.time = DateTime.Now;
                semp.employees = tabelaEmployee.GetById(req.EmployeeID, false);
                semp.services = tabelaServices.GetById(req.ServiceID, false);
                tabelaServicesEmployees.Save(semp);
                return true;
            }
            catch
            {
                return false;
            }
        }
        public bool unbindEmployeeFromService(ReqUBEmp req)
        {
            NHibernate.Expression.ICriterion[] searchCrit = new NHibernate.Expression.ICriterion[3];
            searchCrit[0] = NHibernate.Expression.Expression.Eq("id_employees", req.EmployeeID);
            searchCrit[1] = NHibernate.Expression.Expression.Eq("id_services", req.ServiceID);
            searchCrit[2] = NHibernate.Expression.Expression.Eq("time", req.Time);
            List<services_employees> elements = tabelaServicesEmployees.GetByCriteria(searchCrit);
            foreach (services_employees el in elements)
            {
                tabelaServicesEmployees.Delete(el);
            }
            return true;
        }

        public ResHEmp hireEmployee(ReqHEmp req)
        {
            DBAccess.employees emp = new DBAccess.employees();
            personal_data pers = new personal_data();
            ResHEmp retVal = new ResHEmp();
            //Check conditions
            if (
                req == null
                || req.Salary == null || req.Salary.Length == 0
                || req.Name.Length == 0
                || req.Surname.Length == 0
                || req.Name.Length > 50
                || req.Surname.Length > 255
                || req.City.Length > 50
                || req.Street.Length >100
                || req.House_nr.Length > 6
                || req.Flat_nr.Length > 6
                || req.Postal_code.Length > 5
                || req.Phone.Length > 20
                || req.Pesel.Length != 11
                )
                return _retFalse();
            
//            NHibernate.Expression.ICriterion[] searchCrit = new NHibernate.Expression.ICriterion[2];
//            searchCrit[0] = NHibernate.Expression.Expression.Eq("personal_data.pesel", req.Pesel);
//            searchCrit[1] = NHibernate.Expression.Expression.IsEmpty("hired_to");
//            List<employees> elements = tabelaEmployee.GetByCriteria(searchCrit);
//            if (elements.Count > 0)
//                return _retFalse();

            pers.name = req.Name;
            pers.surname = req.Surname;
            pers.pesel = req.Pesel;
            pers.street = req.Street;
            pers.house_nr = req.House_nr;
            pers.flat_nr = req.Flat_nr;
            pers.postal_code = req.Postal_code;
            pers.city = req.City;
            pers.phone = req.Phone;

            dict_employees dictEmp = ((dict_employees)tabelaDictEmployee.GetById(0, false));
            try
            {
                emp.salary = decimal.Parse(req.Salary);
            }
            catch
            {
                return _retFalse();
            }
            emp.hied_from = DateTime.Now;
            emp.hired_to = null;
            dictEmp.Addemployees(emp);
            if (!emp.IsValid || !pers.IsValid)
                return _retFalse();
            try
            {
                tabelaEmployee.SaveOrUpdate(emp);
                pers.Addemployees(emp);
                tabelaPersonalData.SaveOrUpdate(pers);
                retVal.IsOK = true;
                retVal.EmployeeID = emp.id;
                return retVal;
            }
            catch
            {
                return _retFalse();
            }
        }

        public void suckEmployee() { }

        public void updateEmployee() { }

        public List<ResListEmp> getAllEmployee() 
        {
            List<ResListEmp> result = new List<ResListEmp>();
            ResListEmp temp;
            foreach (employees emp in tabelaEmployee.GetAll())
            {
                if (emp.hired_to != null && emp.hired_to < DateTime.Now)
                    continue;
                temp = new ResListEmp();
                temp.Id = emp.id;
                temp.Name = emp.personal_data.name;
                temp.Surname = emp.personal_data.surname;
                temp.Pesel = emp.personal_data.pesel;
                result.Add(temp);
            }

            return result;

        }
        private ResListEmp _fetchEmpData(employees emp)
        {
            ResListEmp temp = new ResListEmp();
            temp.Id = emp.id;
            temp.Name = emp.personal_data.name;
            temp.Surname = emp.personal_data.surname;
            temp.Pesel = emp.personal_data.pesel;
            return temp;
        }
        private ResHEmp _retFalse()
        {
            ResHEmp res = new ResHEmp();
            res.IsOK = false;
            return res;
        }

        public List<ResListEmpServices> getAllEmployeeServices()
        {
            List<ResListEmpServices> result = new List<ResListEmpServices>();
            ResListEmpServices temp;
            Service tmpService = new Service();
            foreach (services_employees emp in tabelaServicesEmployees.GetAll())
            {
                if (emp.employees.hired_to != null && emp.employees.hired_to < DateTime.Now)
                    continue;
                temp = new ResListEmpServices();
                temp.Employee = _fetchEmpData(emp.employees);
                temp.Service = tmpService.GetFullServiceById(emp.id_services);
                temp.Time = emp.time;
                result.Add(temp);
            }
            return result;
        }

        public List<ResListEmpHolidays> getAllEmployeeHoliays(int EmployeeID)
        {
            List<ResListEmpHolidays> result = new List<ResListEmpHolidays>();
            ResListEmpHolidays tmpItem;
            ResListEmp emp = _fetchEmpData(tabelaEmployee.GetById(EmployeeID, true));
            NHibernate.Expression.ICriterion[] searchCrit = new NHibernate.Expression.ICriterion[1];
            searchCrit[0] = NHibernate.Expression.Expression.Eq("employees_id", EmployeeID);
            foreach (employees_break empHolidays in tabelaEmployeesHolidays.GetByCriteria(searchCrit))
            {
                tmpItem = new ResListEmpHolidays();
                tmpItem.Employee = emp;
                tmpItem.From = empHolidays.date_from.Value;
                tmpItem.To = empHolidays.date_to.Value;
                tmpItem.Description = empHolidays.description;
                tmpItem.Type = empHolidays.dict_break.name;
                tmpItem.Id = empHolidays.id;
                result.Add(tmpItem);
            }
            return result;
        }
        public List<ResListEmpHolidayTypes> getAllEmployeeHolidayTypes()
        {
            List<ResListEmpHolidayTypes> result = new List<ResListEmpHolidayTypes>();
            ResListEmpHolidayTypes tmpItem;
            foreach (dict_break dict in tabelaEmployeesHolidayTypes.GetAll())
            {
                tmpItem = new ResListEmpHolidayTypes();
                tmpItem.Id = dict.id;
                tmpItem.Name = dict.name;
                tmpItem.Description = dict.description;
                result.Add(tmpItem);
            }
            return result;
        }

        public bool setUrlopEmployee(ReqUEmp request)
        {
            NHibernate.Expression.ICriterion[] searchCrit = new NHibernate.Expression.ICriterion[3];
            searchCrit[0] = NHibernate.Expression.Expression.Eq("employees_id", request.EmployeeId);
//            searchCrit[1] = NHibernate.Expression.Expression.Between("date_from", new DateTime?(request.StartDay), new DateTime?(request.EndDay));
//            searchCrit[2] = NHibernate.Expression.Expression.Between("date_to", new DateTime?(request.StartDay), new DateTime?(request.EndDay));
            searchCrit[1] = NHibernate.Expression.Expression.Between("date_from", request.StartDay, request.EndDay);
            searchCrit[2] = NHibernate.Expression.Expression.Between("date_to", request.StartDay, request.EndDay);
            List<employees_break> elements = tabelaEmployeesHolidays.GetByCriteria(searchCrit);
            if (elements.Count > 0)
                return false;
            if (request.StartDay < DateTime.Now.AddYears(-2) || request.EndDay < request.StartDay)
                return false;
            employees_break empBreak = new employees_break();
            empBreak.employees = tabelaEmployee.GetById(request.EmployeeId, true);
            empBreak.dict_break = tabelaEmployeesHolidayTypes.GetById(request.Type, true);
            empBreak.date_from = request.StartDay;
            empBreak.date_to = request.EndDay;
            empBreak.description = request.Description;
            if (!empBreak.IsValid)
                return false;
            tabelaEmployeesHolidays.Save(empBreak);
            return true;
        }

        public bool removeUrlopEmployee(int IDUrlop)
        {
            employees_break emp = tabelaEmployeesHolidays.GetById(IDUrlop, true);
            if (emp == null)
                return false;
            try
            {
                tabelaEmployeesHolidays.Delete(emp);
                return true;
            }
            catch
            {
                return false;
            }
        }
        public ResSEmp sackEmployee(int employeeID)
        {
            ResSEmp result = new ResSEmp();
            employees emp = tabelaEmployee.GetById(employeeID, false);
            foreach (employees_break empBreak in emp.employees_break)
            {
                if (empBreak.date_to >= DateTime.Now)
                    return result;
            }
            if (emp == null)
                return result;
            try
            {
                if (!deleteEmployeeServices(employeeID))
                    return result;
                emp.hired_to = DateTime.Now;
                tabelaEmployee.SaveOrUpdate(emp);
                result.IsOk = true;
                result.EndDate = DateTime.Now;
                return result;
            }
            catch
            {
                return result;
            }
        }
        private bool deleteEmployeeServices(int employeeID)
        {
            NHibernate.Expression.ICriterion[] searchCrit = new NHibernate.Expression.ICriterion[1];
            searchCrit[0] = NHibernate.Expression.Expression.Eq("id_employees", employeeID);
            try
            {
                List<services_employees> elements = tabelaServicesEmployees.GetByCriteria(searchCrit);
                foreach (services_employees el in elements)
                {
                    tabelaServicesEmployees.Delete(el);
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}
